package com.youhome.service.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.youhome.common.config.ZillowConfig;
import com.youhome.common.enums.ZillowTypeEnum;
import com.youhome.common.exception.CustomException;
import com.youhome.common.response.Result;
import com.youhome.common.response.ResultCode;
import com.youhome.service.model.Zip;
import com.youhome.service.response.*;
import com.youhome.service.service.DownloadService;
import com.youhome.service.service.ZillowService;
import com.youhome.service.service.ZipService;
import com.youhome.service.utils.StringUtil;
import com.youhome.service.utils.ZillowJsonExtractUtils;
import com.youhome.utils.DateUtils;
import com.youhome.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * Created by chen365 on 2019/02/13.
 */
@Service
public class ZillowServiceImpl implements ZillowService {
    @Autowired
    private ZillowConfig zillowConfig;
    @Autowired
    private DownloadService downloadService;
    @Autowired
    private ZipService zipService;

    @Override
    public TimeValueItemResult get_Zip_ZriPerSqft_AllHomes(String zip) {
        String key = "zillow/Zip_ZriPerSqft_AllHomes/" + zip + ".json";
        List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key);
        if (list != null && list.size() > 0) {
            return list.get(list.size() - 1);
        }
        return null;
    }

    @Override
    public Double getForecastRent(String zip, Double livingArea) {
        Double forecastRent = null;
        if (!StringUtils.isEmpty(zip)) {
            TimeValueItemResult timeSeriesDataAllRentMedian = get_Zip_ZriPerSqft_AllHomes(zip);
            if (timeSeriesDataAllRentMedian != null) {
                Double size = livingArea;
                Double price = Double.valueOf(timeSeriesDataAllRentMedian.getValue());
                if (size != null && size > 0 && price != null && price > 0) {
                    forecastRent = size * price;
                }
            }
        }
        return forecastRent;
    }

    /***
     * 房屋价格指数
     * @param type 类型
     * @param zip 邮编
     * @return
     */
    @Override
    public ZhviResult get_Zip_Zhvi_Summary_AllHomes(Integer type, String zip) {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + zip + ".json";
        String json = downloadService.downloadJsonFromOSS(key);
        //重新获取相邻邮编数据
        if (StringUtils.isEmpty(json)) {
            json = getNextToZipJsonByZips(dir, zip);
        }
        return ZillowJsonExtractUtils.extractZhviResultByJson(json);
    }

    /**
     * 买方卖方指数
     *
     * @param type
     * @param zip
     * @return
     */
    @Override
    public BuyerSellerResult get_Buyer_Seller_Index_Zip(Integer type, String zip) {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + zip + ".json";

        String json = downloadService.downloadJsonFromOSS(key);
        if (StringUtils.isEmpty(json)) {
            json = getNextToZipJsonByZips(dir, zip);
        }

        return ZillowJsonExtractUtils.extractBuyerSellerResultByJson(json);
    }

    /***
     * 市场健康指数
     * @param type
     * @param zip
     * @return
     */
    @Override
    public MarketHealthResult get_Market_Health_Index_Zip(Integer type, String zip) {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + zip + ".json";
        String json = downloadService.downloadJsonFromOSS(key);

        //重新获取相邻邮编数据
        if (StringUtils.isEmpty(json)) {
            json = getNextToZipJsonByZips(dir, zip);
        }

        return ZillowJsonExtractUtils.extractMarketHealthResultByJson(json);
    }

    /**
     * 时间序列
     *
     * @param type
     * @param zip
     * @param year
     * @return
     * @throws CustomException
     */
    @Override
    public List<TimeValueItemResult> getTimeSeries(Integer type, String zip, Integer year) throws CustomException {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + zip + ".json";
        // 90 : 卖房成功比例  按城市统计	月更新
        // 91 : 中位挂牌时间 以城市为准 	月更新
        // 95 : 房产销售数量 按city统计
        // 104:中位家庭收入   都会区  季度更新
        // 86:贷款能力 87:价格收入比 88:租金能力--季度更新
        boolean isZipSearch = true; //是否按邮编方式查询

        if (type.equals(ZillowTypeEnum.SaleToListRatio_City.getKey()) ||
                type.equals(ZillowTypeEnum.DaysOnZillow_City.getKey()) ||
                type.equals(ZillowTypeEnum.Sale_Counts_Seas_Adj_City.getKey()) ||
                type.equals(ZillowTypeEnum.Affordability_Income.getKey())) {

            //if (type.equals(90) || type.equals(91) || type.equals(95) || type.equals(104)) {
            isZipSearch = false;
            Zip entity = zipService.selectByPrimaryKey(zip);
            if (entity == null) {
                throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
            }
            String city = entity.getCity();
            String state = entity.getState();
            if (StringUtils.isEmpty(city)) {
                throw new CustomException(ResultCode.CITY_NULL);
            }
            if (StringUtils.isEmpty(state)) {
                throw new CustomException(ResultCode.STATE_NULL);
            }
            if (type.equals(ZillowTypeEnum.Sale_Counts_Seas_Adj_City.getKey())) {
                state = StringUtils.stateAbbreviationToAll(state); // 州缩写转全称
            }
            key = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(city) + "_" + StringUtils.replaceBlankAndComma(state) + ".json";
        }

        if (type.equals(ZillowTypeEnum.Affordability_Wide_Public_Loan.getKey()) ||
                type.equals(ZillowTypeEnum.Affordability_Wide_Public_Ratio.getKey()) ||
                type.equals(ZillowTypeEnum.Affordability_Wide_Public_Rent.getKey())) {

            //if (type.equals(86) || type.equals(87) || type.equals(88)) {
            isZipSearch = false;
            Zip entity = zipService.selectByPrimaryKey(zip);
            if (entity == null)
                throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
            String metro = entity.getMetro();
            if (StringUtils.isEmpty(metro)) {
                throw new CustomException(ResultCode.METRO_NULL);
            }
            if (type.equals(ZillowTypeEnum.Affordability_Wide_Public_Loan.getKey())) {
                key = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + "_mortgage_affordability.json";
            }
            if (type.equals(ZillowTypeEnum.Affordability_Wide_Public_Ratio.getKey())) {
                key = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + "_price_to_income.json";
            }
            if (type.equals(ZillowTypeEnum.Affordability_Wide_Public_Rent.getKey())) {
                key = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + "_rent_affordability.json";
            }
        }
        String json = downloadService.downloadJsonFromOSS(key);
        //重新获取相邻邮编数据
        if (StringUtils.isEmpty(json) && isZipSearch) {
            json = getNextToZipJsonByZips(dir, zip);
        }
        try {
            if (StringUtils.isEmpty(json)) {
                return null;
            }
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject.get("time") == null) {
                return null;
            }
            String time = jsonObject.get("time").toString();

            ObjectMapper mapper = new ObjectMapper();
            List<TimeValueItemResult> timeValueItemResult = mapper.readValue(time, new TypeReference<List<TimeValueItemResult>>() {
            });
            //0年 表示获取所有数据
            if (year.equals(0)) {
                return timeValueItemResult;
            }
            String dateFormat = "yyyy-MM";
            Date eTime = new Date();
            Date bTime = DateUtils.addYear(eTime, -year);
            //开始截取的时间
            String startTime = DateUtils.formatDate(bTime, dateFormat);
            Boolean flag = false; // 开始截取标识
            List<TimeValueItemResult> items = new ArrayList<>();
            for (TimeValueItemResult item : timeValueItemResult) {
                if (item.getTime().compareTo(startTime) > -1) {
                    flag = true;
                }
                if (flag) {
                    items.add(item);
                }
            }
            return items;
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException(ResultCode.ERROR);
        }
    }

    /**
     * 房屋租金指数-全部-汇总
     *
     * @param type
     * @param zip
     * @return
     */
    @Override
    public ZriResult get_Zip_Zri_AllHomes_Summary(Integer type, String zip) {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + zip + ".json";
        String json = downloadService.downloadJsonFromOSS(key);
        //重新获取相邻邮编数据
        if (StringUtils.isEmpty(json)) {
            json = getNextToZipJsonByZips(dir, zip);
        }
        return ZillowJsonExtractUtils.extractZriResultByJson(json);
    }

    /**
     * 租售比
     *
     * @param type
     * @param zip
     * @return
     */
    @Override
    public BreakEvenPRResult get_Break_Even_PR(Integer type, String zip) {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + zip + ".json";
        System.err.println(key);
        String json = downloadService.downloadJsonFromOSS(key);

        //重新获取相邻邮编数据
        if (StringUtils.isEmpty(json)) {
            json = getNextToZipJsonByZips(dir, zip);
        }

        return ZillowJsonExtractUtils.extractBreakEvenPRResultByJson(json);
    }

    /***
     * 租金涨幅百分比预测
     * @param type
     * @param zip
     * @return
     */
    @Override
    public ZriForecastPublicResult get_Zri_Forecast_Public(Integer type, String zip) throws CustomException {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        Zip entity = zipService.selectByPrimaryKey(zip);
        if (entity == null) {
            throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
        }
        String metro = entity.getMetro();
        if (StringUtils.isEmpty(metro)) {
            throw new CustomException(ResultCode.METRO_NULL);
        }
        String key = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + ".json";
        String json = downloadService.downloadJsonFromOSS(key);

        return ZillowJsonExtractUtils.extractZriForecastPublicResultByJson(json);
    }

    /**
     * 贷款利息
     *
     * @param type
     * @param year
     * @return
     */
    @Override
    public List<TimeValueItemResult> get_loan_interest(Integer type, Integer year) {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + dir + "_AVG.json";  //平均值
        String json = downloadService.downloadJsonFromOSS(key);
        if (!StringUtils.isEmpty(json)) {
            List<TimeValueItemResult> timeValueItemResult = ZillowJsonExtractUtils.getTimeSeriesDataByYear(json, year);
            return timeValueItemResult;
        }
        return null;
    }

    /**
     * 存量房数字及高中低价位房产分布比例 按大都会区统计
     *
     * @param format
     * @param zip
     * @param year
     * @return
     * @throws CustomException
     */
    @Override
    public InventoryResult get_InventoryMeasure_Tiers_Metro_Public(String format, String zip, Integer year) throws CustomException {
        String dir = ZillowTypeEnum.InventoryMeasure_Tiers_Metro_Public.getValue();
        Zip entity = zipService.selectByPrimaryKey(zip);
        if (entity == null) {
            throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
        }
        String metro = entity.getMetro();
        if (StringUtils.isEmpty(metro)) {
            throw new CustomException(ResultCode.SUCCESS);
        }

        String str_variable;

        if (format.equals("count")) {
            str_variable = "Inventory Seasonally Adjusted";
        } else if (format.equals("pct")) {
            str_variable = "TierShare";
        } else {
            return null;
        }

        String key_top = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + "_"
                + StringUtils.replaceBlankAndComma(str_variable) + "_top_tier.json";

        String key_middle = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + "_"
                + StringUtils.replaceBlankAndComma(str_variable) + "_middle_tier.json";

        String key_bottom = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + "_"
                + StringUtils.replaceBlankAndComma(str_variable) + "_bottom_tier.json";

        String json_top = downloadService.downloadJsonFromOSS(key_top);
        String json_middle = downloadService.downloadJsonFromOSS(key_middle);
        String json_bottom = downloadService.downloadJsonFromOSS(key_bottom);
        InventoryResult inventoryResult = new InventoryResult();

        if (!StringUtils.isEmpty(json_top)) {
            List<TimeValueItemResult> topResult = ZillowJsonExtractUtils.getSeriesDataByYear(json_top, year);
            inventoryResult.setTop(topResult);
        }
        if (!StringUtils.isEmpty(json_middle)) {
            List<TimeValueItemResult> middleResult = ZillowJsonExtractUtils.getSeriesDataByYear(json_middle, year);
            inventoryResult.setMiddle(middleResult);
        }
        if (!StringUtils.isEmpty(json_bottom)) {
            List<TimeValueItemResult> bottomResult = ZillowJsonExtractUtils.getSeriesDataByYear(json_bottom, year);
            inventoryResult.setBottom(bottomResult);
        }

        return inventoryResult;
    }

    /**
     * 负资产率都会区统计
     *
     * @param type
     * @param zip
     * @return
     * @throws CustomException
     */
    @Override
    public MetroNETiersResult get_Metro_NETiers(Integer type, String zip) throws CustomException {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        Zip entity = zipService.selectByPrimaryKey(zip);
        if (entity == null) {
            throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
        }
        String metro = entity.getMetro();
        if (StringUtils.isEmpty(metro)) {
            throw new CustomException(ResultCode.METRO_NULL);
        }
        String key = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + ".json";
        String json = downloadService.downloadJsonFromOSS(key);
        MetroNETiersResult metroNETiersResult = new MetroNETiersResult();
        if (!StringUtils.isEmpty(json)) {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (!StringUtils.isEmpty(jsonObject.get("BottomTierNEPct"))) {
                metroNETiersResult.setBottom_tier_ne_pct(Double.valueOf(jsonObject.getString("BottomTierNEPct")));
            }
            if (!StringUtils.isEmpty(jsonObject.get("MiddleTierNEPct"))) {
                metroNETiersResult.setMiddle_tier_ne_pct(Double.valueOf(jsonObject.getString("MiddleTierNEPct")));
            }
            if (!StringUtils.isEmpty(jsonObject.get("TopTierNEPct"))) {
                metroNETiersResult.setTop_tier_ne_pct(Double.valueOf(jsonObject.getString("TopTierNEPct")));
            }
        }
        return metroNETiersResult;
    }

    /***
     *负资产率按城市统计
     * @param type
     * @param zip
     * @param t
     * @return
     */
    @Override
    public List<TimeValueItemResult> get_NegativeEquity_Public(Integer type, String zip, Integer t) throws CustomException {
        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        String key = "zillow/" + dir + "/" + zip + ".json";
        if (type.equals(101)) {
            // 101 : 负资产率 按城市 季度更新
            Zip entity = zipService.selectByPrimaryKey(zip);
            if (entity == null) {
                throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
            }
            String city = entity.getCity();
            String state = entity.getState();
            String county = entity.getCounty();
            if (StringUtils.isEmpty(city)) {
                throw new CustomException(ResultCode.CITY_NULL);
            }
            if (StringUtils.isEmpty(county)) {
                throw new CustomException(ResultCode.COUNTY_NULL);
            }
            if (StringUtils.isEmpty(state)) {
                throw new CustomException(ResultCode.STATE_NULL);
            }
            key = "zillow/" + dir + "/city_"
                    + StringUtils.replaceBlankAndComma(city) + "_"  //城市
                    + StringUtils.replaceBlankAndComma(county) + "_" //郡县
                    + StringUtils.replaceBlankAndComma(state)  //州
                    + ".json";
        }
        String json = downloadService.downloadJsonFromOSS(key);
        try {
            if (!StringUtils.isEmpty(json)) {
                JSONObject jsonObject = JSONObject.parseObject(json);
                if (jsonObject.get("time") != null) {
                    String time = jsonObject.get("time").toString();
                    ObjectMapper mapper = new ObjectMapper();
                    List<TimeValueItemResult> timeValueItemResult = mapper.readValue(time, new TypeReference<List<TimeValueItemResult>>() {
                    });
                    //0年 表示获取所有数据
                    if (t != 0 && t > 0) {
                        String dateFormat = "yyyy";
                        Date eTime = new Date();
                        Date bTime = DateUtils.addYear(eTime, -t);
                        //开始截取的时间
                        String startTime = DateUtils.formatDate(bTime, dateFormat);
                        Boolean flag = false; // 开始截取标识
                        List<TimeValueItemResult> items = new ArrayList<>();
                        for (TimeValueItemResult item : timeValueItemResult) {
                            String q = item.getTime().substring(0, item.getTime().indexOf("Q"));
                            if (q.compareTo(startTime) > -1) {
                                flag = true;
                            }
                            if (flag) {
                                items.add(item);
                            }
                        }
                        return items;
                    }
                    return timeValueItemResult;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<TimeSeriesItem> selectMOM(String zip, String time) throws CustomException {
        if (time.equals("max")) {
            time = "0";
        }
        //http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_AllHomes/01001.json
        String key = "zillow/Zip_Zhvi_AllHomes/" + zip + ".json";
        List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key);
        //重新获取相邻邮编数据
        if (list == null || list.size() < 1) {
            String type = "Zip_Zhvi_AllHomes";
            list = getListNextToZipJsonByZips(type, zip);
        }
        List<TimeSeriesItem> moms = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                if (i > 0) {
                    Double ratio = 0.0;
                    Date current_time = DateUtils.StrToDate(list.get(i).getTime(), "yyyy-MM");
                    if (!StringUtils.isEmpty(list.get(i).getValue()) && !StringUtils.isEmpty(list.get(i - 1).getValue())) {
                        Double current_value = Double.valueOf(list.get(i).getValue()); //当前月的值
                        Double last_value = Double.valueOf(list.get(i - 1).getValue()); //上月的值
                        if (last_value != 0) {
                            //房价环比增长率(moms)  环比增长率=(本期数-上期数)/上期数×100%。
                            ratio = (current_value - last_value) / last_value * 100;
                        }
                    }
                    TimeSeriesItem mom = new TimeSeriesItem();
                    mom.setTime(DateUtils.DateToStr(current_time, "yyyy-MM"));
                    mom.setValue(ratio);
                    moms.add(mom);
                }
            }
        }
        if (!time.equals("0")) {
            return ZillowJsonExtractUtils.getSubString(moms, time, "yyyy-MM");
        } else {
            return moms;
        }
    }

    @Override
    public List<TimeSeriesItem> selectYOY(String zip, String time) throws CustomException {
        if (time.equals("max")) {
            time = "0";
        }

        //http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_AllHomes/01001.json
        String key = "zillow/Zip_Zhvi_AllHomes/" + zip + ".json";
        List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key);

        //重新获取相邻邮编数据
        if (list == null || list.size() < 1) {
            String type = "Zip_Zhvi_AllHomes";
            list = getListNextToZipJsonByZips(type, zip);
        }
        List<TimeSeriesItem> yoys = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Double last_value = 0.0;
                if (i > 12) {
                    Date current_time = DateUtils.StrToDate(list.get(i).getTime(), "yyyy-MM");
                    Double ratio = 0.0;
                    if (!StringUtils.isEmpty(list.get(i).getValue()) && !StringUtils.isEmpty(list.get(i - 12).getValue())) {
                        Double current_value = Double.valueOf(list.get(i).getValue()); //当前月的值
                        last_value = Double.valueOf(list.get(i - 12).getValue()); //上年的值
                        if (last_value != 0) {
                            //房价环比增长率(moms)  环比增长率=(本期数-上期数)/上期数×100%。
                            ratio = (current_value - last_value) / last_value * 100;
                        }
                    }
                    TimeSeriesItem mom = new TimeSeriesItem();
                    mom.setTime(DateUtils.DateToStr(current_time, "yyyy-MM"));
                    mom.setValue(ratio);
                    yoys.add(mom);
                }
            }
        }

        if (!time.equals("0")) {
            return ZillowJsonExtractUtils.getSubString(yoys, time, "yyyy-MM");
        } else {
            return yoys;
        }
    }

    @Override
    public List<TimeValueItemResult> selectMedianRentByZip(String zipcode, String time) throws CustomException {
        if (time.equals("max")) {
            time = "0";
        }

        String key = "zillow/Zip_Zri_AllHomesPlusMultifamily/" + zipcode + ".json";
        List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key, time);
        //重新获取相邻邮编数据
        if (list == null || list.size() < 1) {
            list = getListNextToZipJsonByZips("Zip_Zri_AllHomesPlusMultifamily", zipcode, time);
        }
        return list;
    }

    @Override
    public List<TimeSeriesItem> selectRentalYieldByZip(String zipcode, String time) throws CustomException {
        if (time.equals("max")) {
            time = "0";
        }
        String key_Zip_Zhvi_AllHomes = "zillow/Zip_Zhvi_AllHomes/" + zipcode + ".json"; //房价
        List<TimeValueItemResult> timeValueItemResults_Zip_Zhvi_AllHomes = downloadService.downloadTimeValuesFromOSS(key_Zip_Zhvi_AllHomes, time);
        if (timeValueItemResults_Zip_Zhvi_AllHomes == null || timeValueItemResults_Zip_Zhvi_AllHomes.size() < 1) {
            timeValueItemResults_Zip_Zhvi_AllHomes = getListNextToZipJsonByZips("Zip_Zhvi_AllHomes", zipcode, time);
        }
        String key_Zip_Zri_AllHomesPlusMultifamily = "zillow/Zip_Zri_AllHomesPlusMultifamily/" + zipcode + ".json";  //租金
        List<TimeValueItemResult> timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily = downloadService.downloadTimeValuesFromOSS(key_Zip_Zri_AllHomesPlusMultifamily, time);
        if (timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily == null || timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily.size() < 1) {
            timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily = getListNextToZipJsonByZips("Zip_Zri_AllHomesPlusMultifamily", zipcode, time);
        }
        List<TimeSeriesItem> rent_items = new ArrayList<>(); //租金
        List<TimeSeriesItem> price_items = new ArrayList<>();//房价
        List<TimeSeriesItem> rewards = new ArrayList<>();  //租金回报
        if (timeValueItemResults_Zip_Zhvi_AllHomes != null && timeValueItemResults_Zip_Zhvi_AllHomes.size() > 0) {
            price_items = convertDoubleTS(timeValueItemResults_Zip_Zhvi_AllHomes);
        }
        if (timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily != null && timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily.size() > 0) {
            rent_items = convertDoubleTS(timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily);
        }
        if (rent_items.size() > 0 && price_items.size() > 0) {
            rewards = calculateRentalYield(rent_items, price_items);
        }
        if (rewards != null && rewards.size() > 0) {
            return rewards;
        } else {
            throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
        }
    }

    @Override
    public List<TimeValueItemResult> get_InventoryMeasure_Tiers_Metro_Public_By_Tier_Format(Integer type, String tier, String format, String zip, Integer year) throws CustomException {

        String dir = ZillowTypeEnum.getEnumByKey(type).getValue();
        Zip entity = zipService.selectByPrimaryKey(zip);
        if (entity == null) {
            throw new CustomException(ResultCode.NO_DATA_WAS_FOUND);
        }
        String metro = entity.getMetro();
        if (StringUtils.isEmpty(metro)) {
            throw new CustomException(ResultCode.METRO_NULL);
        }

        String key = null;
        String str_variable = null;
        String str_tier = null;
        if (format.equals("count")) {
            str_variable = "Inventory Seasonally Adjusted";
        } else if (format.equals("pct")) {
            str_variable = "TierShare";
        } else {
            throw new CustomException(ResultCode.ERROR_TIER_TYPE);
        }

        if (tier.equals("top")) {
            str_tier = "Top Tier";
        } else if (tier.equals("middle")) {
            str_tier = "Middle Tier";
        } else if (tier.equals("bottom")) {
            str_tier = "Bottom Tier";
        } else {
            throw new CustomException(ResultCode.ERROR_FORMAT);
        }

        key = "zillow/" + dir + "/" + StringUtils.replaceBlankAndComma(metro) + "_"
                + StringUtils.replaceBlankAndComma(str_variable) + "_"
                + StringUtils.replaceBlankAndComma(str_tier) + ".json";

        String json = downloadService.downloadJsonFromOSS(key);

        if (!StringUtils.isEmpty(json)) {
            return ZillowJsonExtractUtils.getSeriesDataByYear(json, year);
        }
        return null;
    }

    @Override
    public InventoryResult inventory(String type, String zip) {
        int year = 1;

        Zip entity = zipService.selectByPrimaryKey(zip);
        if (entity == null) {
            return null;
        }
        String metro = entity.getMetro();
        if (org.springframework.util.StringUtils.isEmpty(metro)) {
            System.err.println("================>>metro is null");
            return null;
        }
        String str_variable = null;
        if (type.equals("count")) {
            str_variable = "Inventory Seasonally Adjusted";
        } else if (type.equals("pct")) {
            str_variable = "TierShare";
        } else {
            return null;
        }

        String key_top = "zillow/InventoryMeasure_Tiers_Metro_Public/" + StringUtil.replaceBlankAndComma(metro) + "_"
                + StringUtil.replaceBlankAndComma(str_variable) + "_top_tier.json";

        String key_middle = "zillow/InventoryMeasure_Tiers_Metro_Public/" + StringUtil.replaceBlankAndComma(metro) + "_"
                + StringUtil.replaceBlankAndComma(str_variable) + "_middle_tier.json";

        String key_bottom = "zillow/InventoryMeasure_Tiers_Metro_Public/" + StringUtil.replaceBlankAndComma(metro) + "_"
                + StringUtil.replaceBlankAndComma(str_variable) + "_bottom_tier.json";

        //System.err.println(key_top);
        //System.err.println(key_middle);
        //System.err.println(key_bottom);
        String json_top = downloadService.downloadJsonFromOSS(key_top);
        String json_middle = downloadService.downloadJsonFromOSS(key_middle);
        String json_bottom = downloadService.downloadJsonFromOSS(key_bottom);
        InventoryResult inventoryResult = new InventoryResult();
        if (!org.springframework.util.StringUtils.isEmpty(json_top)) {
            List<TimeValueItemResult> topResult = ZillowJsonExtractUtils.getSeriesDataByYear(json_top, year);
            inventoryResult.setTop(topResult);
        }
        if (!org.springframework.util.StringUtils.isEmpty(json_middle)) {
            List<TimeValueItemResult> middleResult = ZillowJsonExtractUtils.getSeriesDataByYear(json_middle, year);
            inventoryResult.setMiddle(middleResult);
        }
        if (!org.springframework.util.StringUtils.isEmpty(json_bottom)) {
            List<TimeValueItemResult> bottomResult = ZillowJsonExtractUtils.getSeriesDataByYear(json_bottom, year);
            inventoryResult.setBottom(bottomResult);
        }
        return inventoryResult;
    }

    /**
     * 计算租金回报
     *
     * @param rent_items  租金
     * @param price_items 房价
     * @return
     */
    public List<TimeSeriesItem> calculateRentalYield(List<TimeSeriesItem> rent_items, List<TimeSeriesItem> price_items) {
        if (rent_items.size() > 0 && price_items.size() > 0) {
            List<TimeSeriesItem> rewards = new ArrayList<>();  //租金回报
            for (TimeSeriesItem rent_item : rent_items) {
                for (TimeSeriesItem price_item : price_items) {
                    if (rent_item.getTime().compareTo(price_item.getTime()) == 0) {
                        if (rent_item.getValue() != null && price_item.getValue() != null && price_item.getValue() != 0) {
                            TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                            timeSeriesItem.setTime(rent_item.getTime());
                            // 租金回报 = 租金 * 12 / 房价 * 100
                            double v = rent_item.getValue() * 12 / price_item.getValue() * 100;
                            timeSeriesItem.setValue(v);
                            rewards.add(timeSeriesItem);
                        }
                        break;
                    }
                }
            }
            return rewards;
        }
        return null;
    }

    /***
     * 重新获取相邻邮编数据
     * @param type 文件路径
     * @param zip 邮编
     * @return
     */
    public List<TimeValueItemResult> getListNextToZipJsonByZips(String type, String zip) {
        List<TimeValueItemResult> list = new ArrayList<>();
        List<String> zipCodes = zipService.selectSameCityZipsByZip(zip);
        System.err.println("==============>>zipCodes:" + zipCodes.toString());
        if (zipCodes != null && zipCodes.size() > 0) {
            final int len = zipCodes.size();
            for (int i = 0; i < len; i++) {
                String postcode = StringUtils.getZip(zipCodes, zip);
                System.err.println("====相邻zip:" + postcode);
                zipCodes.remove(postcode); //数组中删除与zip 最近的邮编
                String key = "zillow/" + type + "/" + postcode + ".json";
                list = downloadService.downloadTimeValuesFromOSS(key); //重新获取json 数据
                if (list != null && list.size() > 0) {
                    break;
                }
            }
        }
        return list;
    }

    /***
     * 重新获取相邻邮编数据
     * @param type 文件路径
     * @param zip 邮编
     * @return
     */
    public List<TimeValueItemResult> getListNextToZipJsonByZips(String type, String zip, String time) {
        List<TimeValueItemResult> list = new ArrayList<>();
        List<String> zipCodes = zipService.selectSameCityZipsByZip(zip);
        System.err.println("==============>>zipCodes:" + zipCodes.toString());
        if (zipCodes != null && zipCodes.size() > 0) {
            final int len = zipCodes.size();
            for (int i = 0; i < len; i++) {
                String postcode = StringUtils.getZip(zipCodes, zip);
                System.err.println("====相邻zip:" + postcode);
                zipCodes.remove(postcode); //数组中删除与zip 最近的邮编
                String key = "zillow/" + type + "/" + postcode + ".json";
                list = downloadService.downloadTimeValuesFromOSS(key, time); //重新获取json 数据
                if (list != null && list.size() > 0) {
                    break;
                }
            }
        }
        return list;
    }

    /***
     * 重新获取相邻邮编数据
     * @param type 文件路径
     * @param zip 邮编
     * @return json 字符串
     */
    public String getNextToZipJsonByZips(String type, String zip) {
        if (zillowConfig.getIsSearchAdjacentZip()) {
            String json = null;
            String key;
            List<String> zipCodes = zipService.selectSameCityZipsByZip(zip);
            System.err.println("==============>>zipCodes:" + zipCodes.toString());
            if (zipCodes != null && zipCodes.size() > 0) {
                final int len = zipCodes.size();
                for (int i = 0; i < len; i++) {
                    String postcode = StringUtils.getZip(zipCodes, zip);
                    System.err.println("====相邻zip:" + postcode);
                    zipCodes.remove(postcode); //数组中删除与zip 最近的邮编
                    key = "zillow/" + type + "/" + postcode + ".json";
                    json = downloadService.downloadJsonFromOSS(key); //重新获取json 数据
                    if (!StringUtils.isEmpty(json)) {
                        break;
                    }
                }
            }
            return json;
        }

        return null;
    }

    /**
     * 1b/2b/3b/4b/5b+房价变化  数据格式化，值由字符转成 double
     *
     * @param items 原数据
     * @return
     */
    public List<TimeSeriesItem> convertDoubleTS(List<TimeValueItemResult> items) {
        List<TimeSeriesItem> list = null;
        if (items != null && items.size() > 0) {
            list = new ArrayList<>();
            for (TimeValueItemResult item : items) {
                TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                timeSeriesItem.setTime(item.getTime());
                String val = item.getValue();
                if (!StringUtils.isEmpty(val)) {
                    timeSeriesItem.setValue(Double.valueOf(val));
                }
                list.add(timeSeriesItem);
            }
        }
        return list;
    }
}
